﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using Sausage.Common;
using Sausage.Web.Code;
using Sausage.Web.DataModel;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class MaintainMaterialHelper
    {
        public static GridModel<object> Select(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMaterial(
                        context.MaintainMaterial.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            (item.State == (int)MaintainDataStateEnum.Confirmed)),
                        query, isWithChild);
            }
        }

        public static GridModel<object> SubmitSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMaterial(
                        context.MaintainMaterial.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            (item.State == (int)MaintainDataStateEnum.Unsubmit ||
                             item.State == (int)MaintainDataStateEnum.AuditRejected)),
                        query, isWithChild);
            }
        }

        public static GridModel<object> AuditSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMaterial(context.MaintainMaterial.Where(item =>
                    organization.Contains(item.OrganizationID) &&
                    (item.State == (int)MaintainDataStateEnum.Submitted ||
                     item.State == (int)MaintainDataStateEnum.ConfirmationRejected))
                    , query, isWithChild);
            }
        }

        public static GridModel<object> ConfirmSelect(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);
            using (var context = new SausageEntities())
            {
                return
                    QueryMaintainMaterial(context.MaintainMaterial.Where(item =>
                    organization.Contains(item.OrganizationID) && item.State == (int)MaintainDataStateEnum.Audited)
                    , query, isWithChild);
            }
        }

        private static GridModel<object> QueryMaintainMaterial(IQueryable<MaintainMaterial> source, JosnPagingQueryModel query, bool isWithChild)
        {
            var result = UIHelper.GetGridModelFromQueryModel<MaintainMaterial>(
                source,
                query.page,
                query.limit,
                GetSortDescriptorFromQueryModel(query.SortModel),
                GetSearchFilterFromQueryModel(query.FilterModel, isWithChild));

            var list = result.Data.Select(item => new
            {
                item.MaintainMaterialID,
                item.QuantityID,
                item.OrganizationID,
                Organization = item.Organization.OrganizationName,
                MaintainCode = item.MaintainQuantity.MaintainCode,
                item.MaterialID,
                Material = item.Material.MaterialName,
                Quantity = item.Quantity,
                Unit = item.Material.Unit,
                Price = item.Price,
                Amount = item.Amount,
                CreateDate = item.CreateDate,
                Applicant = item.Applicant,
                ApplicationDate = item.ApplicationDate,
                Auditor = item.Auditor,
                AuditedDate = item.AuditedDate,
                Approver = item.Approver,
                ApprovedDate = item.ApprovedDate,
                State = item.State,
                IsDelay = item.IsDelay,
                Memo = item.Memo,
                item.Comment
            }).ToList();

            return new GridModel<object>()
            {
                Aggregates = result.Aggregates,
                Data = list,
                Total = result.Total
            };
        }

        public static MaintainMaterial GetMaintainMaterialByID(Guid id)
        {
            using (var context = new SausageEntities())
            {
                return
                    context.MaintainMaterial.Include("Organization").Include("MaintainQuantity").Include("Material").FirstOrDefault(
                        item => item.MaintainMaterialID == id);
            }
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels, bool isWithChild)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property == "OrganizationID" && isWithChild)
                    continue;

                if (item.property.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var targetID = Guid.Parse(item.value);
                    if (targetID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, targetID));
                }
                else if (item.property == "ApplicationDate_L") //startData - begin
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsGreaterThanOrEqualTo, targetDate));
                }
                else if (item.property == "ApplicationDate_H") // startDate - end.
                {
                    var targetDate = DateTime.Parse(item.value);
                    filterList.Add(new FilterDescriptor("ApplicationDate", FilterOperator.IsLessThanOrEqualTo, targetDate));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                var descriptor = new SortDescriptor()
                {
                    Member = item.property,
                    SortDirection =
                        item.direction.ToLower() == "desc"
                            ? ListSortDirection.Descending
                            : ListSortDirection.Ascending
                };

                if (descriptor.Member == "Organization")
                    descriptor.Member = "Organization.OrganizationName";
                else if (descriptor.Member == "MaintainCode")
                    descriptor.Member = "MaintainQuantity.MaintainCode";
                else if (descriptor.Member == "Material")
                    descriptor.Member = "Material.MaterialName";
                sortList.Add(descriptor);
            }
            return sortList;

        }

        public static void DeleteMaintainMaterial(Guid id)
        {
            using (var context = new SausageEntities())
            {
                var maintainMaterial = new MaintainMaterial();
                maintainMaterial.MaintainMaterialID = id;

                context.CreateObjectSet<MaintainMaterial>().Attach(maintainMaterial);
                context.ObjectStateManager.ChangeObjectState(maintainMaterial, EntityState.Deleted);
                context.SaveChanges();
            }
        }

        public static void UpdateMaintainMaterial(MaintainMaterialListRow data)
        {
            using (var context = new SausageEntities())
            {
                var maintainMaterial =
                    context.MaintainMaterial.FirstOrDefault(item => item.MaintainMaterialID == data.MaintainMaterialID);
                if (maintainMaterial == null)
                    return;

                if (maintainMaterial.State != (int)MaintainDataStateEnum.Unsubmit && maintainMaterial.State != (int)MaintainDataStateEnum.AuditRejected)
                    throw new SausageException(string.Format("养护材料已经提交，不允许执行编辑操作。"));

                maintainMaterial.QuantityID = data.QuantityID;
                maintainMaterial.MaterialID = data.MaterialID;
                maintainMaterial.Quantity = data.Quantity;
                maintainMaterial.Price = data.Price;
                maintainMaterial.Amount = data.Quantity * data.Price;
                maintainMaterial.Applicant = Helper.CurrentPrincipal.User.UserName;
                //maintainMaterial.ApplicationDate = data.ApplicationDate;
                maintainMaterial.Memo = data.Memo;

                context.SaveChanges();
            }
        }

        public static void UpdateMaintainMaterialState(Guid id, int state)
        {
            using (var context = new SausageEntities())
            {
                var maintainMaterial = context.MaintainMaterial.FirstOrDefault(item => item.MaintainMaterialID == id);
                if (maintainMaterial == null)
                    return;

                maintainMaterial.State = state;
                context.SaveChanges();
            }
        }

        public static void CreateMaintainMaterial(MaintainMaterialListRow data)
        {
            using (var context = new SausageEntities())
            {
                var maintainMaterial = new MaintainMaterial();

                maintainMaterial.MaintainMaterialID = Guid.NewGuid();
                maintainMaterial.QuantityID = data.QuantityID;
                maintainMaterial.OrganizationID = Helper.CurrentPrincipal.Organization.OrganizationID;
                maintainMaterial.MaterialID = data.MaterialID;
                maintainMaterial.Quantity = data.Quantity;
                maintainMaterial.Price = data.Price;
                maintainMaterial.Amount = data.Quantity * data.Price;
                maintainMaterial.CreateDate = DateTime.Now;
                maintainMaterial.Applicant = Helper.CurrentPrincipal.User.UserName;
                maintainMaterial.ApplicationDate = data.ApplicationDate;
                maintainMaterial.State = (int)MaintainDataStateEnum.Unsubmit;
                maintainMaterial.IsDelay = Helper.IsDelay(data.ApplicationDate);
                maintainMaterial.Memo = data.Memo;

                context.AddToMaintainMaterial(maintainMaterial);
                context.SaveChanges();
            }
        }

        public static void ExecuteSubmit(Guid[] materials)
        {
            if (null != materials && materials.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMaterial.Where(item => materials.Contains(item.MaintainMaterialID)).ToList();

                    foreach (var entity in list)
                    {
                        entity.State = (int)MaintainDataStateEnum.Submitted;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteAudit(Guid[] materials, bool passed, string comment)
        {
            if (null != materials && materials.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMaterial.Where(item => materials.Contains(item.MaintainMaterialID)).ToList();

                    foreach (var maintainMaterial in list)
                    {
                        maintainMaterial.Auditor = Helper.CurrentPrincipal.User.UserName;
                        maintainMaterial.AuditedDate = DateTime.Now;
                        maintainMaterial.Comment = comment;
                        maintainMaterial.State = passed
                                                     ? (int)MaintainDataStateEnum.Audited
                                                     : (int)MaintainDataStateEnum.AuditRejected;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteConfirm(Guid[] materials, bool passed, string comment)
        {
            if (null != materials && materials.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.MaintainMaterial.Where(item => materials.Contains(item.MaintainMaterialID)).ToList();

                    foreach (var maintainMaterial in list)
                    {
                        maintainMaterial.Approver = Helper.CurrentPrincipal.User.UserName;
                        maintainMaterial.ApprovedDate = DateTime.Now;
                        maintainMaterial.Comment = comment;
                        maintainMaterial.State = passed
                                                     ? (int)MaintainDataStateEnum.Confirmed
                                                     : (int)MaintainDataStateEnum.ConfirmationRejected;
                    }
                    context.SaveChanges();
                }
            }
        }
    }
}